import type {
	PickOptions,
	PickUpdateOption,
	PickValue,
	PickValueFunc,
} from '../components/picker/picker';

export function makeDateRangePickOptions(start: Date, end: Date): PickOptions[] {
	const [beginYear, endYear] = [start.getFullYear(), end.getFullYear()];
	const [beginMonth, endMonth] = [start.getMonth(), end.getMonth()];
	const [beginDay, endDay] = [start.getDate(), end.getDate()];
	const years = Array(endYear - beginYear + 1)
		.fill(0)
		.map((_, i) => `${beginYear + i}`.padStart(4, '0'));
	return [
		// year
		years,
		// month
		(selection: PickValue[][], option: PickUpdateOption): string[] => {
			const year =
				selection[option.gid]?.[0] === undefined
					? beginYear
					: parseInt(selection[option.gid][0] + '');
			let bm: number;
			if (year === beginYear) {
				bm = beginMonth + 1;
			} else {
				bm = 1;
			}
			let em: number;
			if (year === endYear) {
				em = endMonth + 1;
			} else {
				em = 12;
			}
			return Array(em - bm + 1)
				.fill(0)
				.map((_, i) => (bm + i + '').padStart(2, '0'));
		},
		// day
		(selection: PickValue[][], option: PickUpdateOption): string[] => {
			const year =
				selection[option.gid]?.[0] === undefined
					? beginYear
					: parseInt(selection[option.gid][0] + '');
			const month =
				selection[option.gid]?.[1] === undefined
					? beginMonth
					: parseInt(selection[option.gid][1] + '');
			let bd: number;
			if (year === beginYear && month === beginMonth + 1) {
				bd = beginDay;
			} else {
				bd = 1;
			}
			let ed: number;
			if (year === endYear && month === endMonth + 1) {
				ed = endDay;
			} else {
				ed = new Date(year, month, 0).getDate();
			}
			return Array(ed - bd + 1)
				.fill(0)
				.map((_, i) => (bd + i + '').padStart(2, '0'));
		},
	];
}

export function makeYearRangePickOptions(
	start: Date | undefined,
	end: Date | undefined,
): PickValue[] {
	const [beginYear, endYear] = [start?.getFullYear() ?? 1970, end?.getFullYear() ?? 9999];
	return Array(endYear - beginYear + 1)
		.fill(0)
		.map((_, i) => (beginYear + i + '').padStart(4, '0'));
}

export function makeMonthRangePickOptions(
	start: Date | undefined,
	end: Date | undefined,
): PickValueFunc {
	const [beginYear, endYear] = [start?.getFullYear() ?? 1970, end?.getFullYear() ?? 9999];
	const [beginMonth, endMonth] = [start?.getMonth() ?? 0, end?.getMonth() ?? 11];
	return (selection: PickValue[][], option: PickUpdateOption): string[] => {
		const year =
			selection[option.gid]?.[0] === undefined
				? beginYear
				: parseInt(selection[option.gid][0] + '');
		let bm: number;
		if (year === beginYear) {
			bm = beginMonth + 1;
		} else {
			bm = 1;
		}
		let em: number;
		if (year === endYear) {
			em = endMonth + 1;
		} else {
			em = 12;
		}
		return Array(em - bm + 1)
			.fill(0)
			.map((_, i) => (bm + i + '').padStart(2, '0'));
	};
}
export function makeDayRangePickOptions(
	start: Date | undefined,
	end: Date | undefined,
): PickValueFunc {
	const [beginYear, endYear] = [start?.getFullYear() ?? 1970, end?.getFullYear() ?? 9999];
	const [beginMonth, endMonth] = [start?.getMonth() ?? 0, end?.getMonth() ?? 11];
	const [beginDay, endDay] = [start?.getDate() ?? 1, end?.getDate()];
	return (selection: PickValue[][], option: PickUpdateOption): string[] => {
		const year =
			selection[option.gid]?.[0] === undefined
				? beginYear
				: parseInt(selection[option.gid][0] + '');
		const month =
			selection[option.gid]?.[1] === undefined
				? beginMonth
				: parseInt(selection[option.gid][1] + '');
		let bd: number;
		if (year === beginYear && month === beginMonth + 1) {
			bd = beginDay;
		} else {
			bd = 1;
		}
		let ed: number;
		if (year === endYear && month === endMonth + 1 && endDay !== undefined) {
			ed = endDay;
		} else if (month === undefined) {
			ed = new Date(year, 0, 0).getDate();
		} else {
			ed = new Date(year, month, 0).getDate();
		}
		return Array(ed - bd + 1)
			.fill(0)
			.map((_, i) => (bd + i + '').padStart(2, '0'));
	};
}

export function makeHourRangePickOptions(
	start: Date | undefined,
	end: Date | undefined,
): PickValue[] {
	const [beginHour, endHour] = [start?.getHours() ?? 0, end?.getHours() ?? 23];
	return Array(endHour - beginHour + 1)
		.fill(0)
		.map((_, i) => (beginHour + i + '').padStart(2, '0'));
}

export function makeMinuteRangePickOptions(
	start: Date | undefined,
	end: Date | undefined,
): PickValueFunc {
	const [beginHour, endHour] = [start?.getHours() ?? 0, end?.getHours() ?? 23];
	const [beginMinute, endMinute] = [start?.getMinutes() ?? 0, end?.getMinutes() ?? 59];
	return (selection: PickValue[][], option: PickUpdateOption): string[] => {
		const hour =
			selection[option.gid]?.[0] === undefined
				? beginHour
				: parseInt(selection[option.gid][0] + '');
		let bm: number;
		if (hour === beginHour) {
			bm = beginMinute;
		} else {
			bm = 0;
		}
		let em: number;
		if (hour === endHour) {
			em = endMinute;
		} else {
			em = 59;
		}
		return Array(em - bm + 1)
			.fill(0)
			.map((_, i) => (bm + i + '').padStart(2, '0'));
	};
}

export function makeSecondRangePickOptions(
	start: Date | undefined,
	end: Date | undefined,
): PickValueFunc {
	const [beginHour, endHour] = [start?.getHours() ?? 0, end?.getHours() ?? 23];
	const [beginMinute, endMinute] = [start?.getMinutes() ?? 0, end?.getMinutes() ?? 59];
	const [beginSecond, endSecond] = [start?.getSeconds() ?? 0, end?.getSeconds() ?? 59];
	return (selection: PickValue[][], option: PickUpdateOption): string[] => {
		const hour =
			selection[option.gid]?.[0] === undefined
				? beginHour
				: parseInt(selection[option.gid][0] + '');
		const minute =
			selection[option.gid]?.[1] === undefined
				? beginMinute
				: parseInt(selection[option.gid][1] + '');
		let bs: number;
		if (hour === beginHour && minute === beginMinute) {
			bs = beginSecond;
		} else {
			bs = 0;
		}
		let es: number;
		if (hour === endHour && minute === endMinute) {
			es = endSecond;
		} else {
			es = 59;
		}
		return Array(es - bs + 1)
			.fill(0)
			.map((_, i) => (bs + i + '').padStart(2, '0'));
	};
}

export function makeHourRangePickOptionsWithDate(
	start: Date | undefined,
	end: Date | undefined,
): PickValueFunc {
	const [beginYear, endYear] = [start?.getFullYear() ?? 1970, end?.getFullYear() ?? 9999];
	const [beginMonth, endMonth] = [start?.getMonth() ?? 0, end?.getMonth() ?? 11];
	const [beginDay, endDay] = [start?.getDate(), end?.getDate()];
	const [beginHour, endHour] = [start?.getHours() ?? 0, end?.getHours() ?? 23];
	return (selection: PickValue[][], option: PickUpdateOption): string[] => {
		const year =
			selection[option.gid]?.[0] === undefined
				? beginYear
				: parseInt(selection[option.gid][0] + '');
		const month =
			selection[option.gid]?.[1] === undefined
				? beginMonth
				: parseInt(selection[option.gid][1] + '');
		const day =
			selection[option.gid]?.[2] === undefined ? beginDay : parseInt(selection[option.gid][2] + '');
		let bh: number;
		if (year === beginYear && month === beginMonth + 1 && day === beginDay) {
			bh = beginHour;
		} else {
			bh = 0;
		}
		let eh: number;
		if (year === endYear && month === endMonth + 1 && day === endDay) {
			eh = endHour;
		} else {
			eh = 23;
		}
		return Array(eh - bh + 1)
			.fill(0)
			.map((_, i) => (bh + i + '').padStart(2, '0'));
	};
}

export function makeMinuteRangePickOptionsWithDate(
	start: Date | undefined,
	end: Date | undefined,
): PickValueFunc {
	const [beginYear, endYear] = [start?.getFullYear() ?? 1970, end?.getFullYear() ?? 9999];
	const [beginMonth, endMonth] = [start?.getMonth() ?? 0, end?.getMonth() ?? 11];
	const [beginDay, endDay] = [start?.getDate(), end?.getDate()];
	const [beginHour, endHour] = [start?.getHours() ?? 0, end?.getHours() ?? 23];
	const [beginMinute, endMinute] = [start?.getMinutes() ?? 0, end?.getMinutes() ?? 59];
	return (selection: PickValue[][], option: PickUpdateOption): string[] => {
		const year =
			selection[option.gid]?.[0] === undefined
				? beginYear
				: parseInt(selection[option.gid][0] + '');
		const month =
			selection[option.gid]?.[1] === undefined
				? beginMonth
				: parseInt(selection[option.gid][1] + '');
		const day =
			selection[option.gid]?.[2] === undefined ? beginDay : parseInt(selection[option.gid][2] + '');
		const hour =
			selection[option.gid]?.[3] === undefined
				? beginHour
				: parseInt(selection[option.gid][3] + '');
		let bm: number;
		if (year === beginYear && month === beginMonth + 1 && day === beginDay && hour === beginHour) {
			bm = beginMinute;
		} else {
			bm = 0;
		}
		let em: number;
		if (year === endYear && month === endMonth + 1 && day === endDay && hour === endHour) {
			em = endMinute;
		} else {
			em = 59;
		}
		return Array(em - bm + 1)
			.fill(0)
			.map((_, i) => (bm + i + '').padStart(2, '0'));
	};
}

export function makeSecondRangePickOptionsWithDate(
	start: Date | undefined,
	end: Date | undefined,
): PickValueFunc {
	const [beginYear, endYear] = [start?.getFullYear() ?? 1970, end?.getFullYear() ?? 9999];
	const [beginMonth, endMonth] = [start?.getMonth() ?? 0, end?.getMonth() ?? 11];
	const [beginDay, endDay] = [start?.getDate(), end?.getDate()];
	const [beginHour, endHour] = [start?.getHours() ?? 0, end?.getHours() ?? 23];
	const [beginMinute, endMinute] = [start?.getMinutes() ?? 0, end?.getMinutes() ?? 59];
	const [beginSecond, endSecond] = [start?.getSeconds() ?? 0, end?.getSeconds() ?? 59];
	return (selection: PickValue[][], option: PickUpdateOption): string[] => {
		const year =
			selection[option.gid]?.[0] === undefined
				? beginYear
				: parseInt(selection[option.gid][0] + '');
		const month =
			selection[option.gid]?.[1] === undefined
				? beginMonth
				: parseInt(selection[option.gid][1] + '');
		const day =
			selection[option.gid]?.[2] === undefined ? beginDay : parseInt(selection[option.gid][2] + '');
		const hour =
			selection[option.gid]?.[3] === undefined
				? beginHour
				: parseInt(selection[option.gid][3] + '');
		const minute =
			selection[option.gid]?.[4] === undefined
				? beginMinute
				: parseInt(selection[option.gid][4] + '');
		let bs: number;
		if (
			year === beginYear &&
			month === beginMonth + 1 &&
			day === beginDay &&
			hour === beginHour &&
			minute === beginMinute
		) {
			bs = beginSecond;
		} else {
			bs = 0;
		}
		let es: number;
		if (
			year === endYear &&
			month === endMonth + 1 &&
			day === endDay &&
			hour === endHour &&
			minute === endMinute
		) {
			es = endSecond;
		} else {
			es = 59;
		}
		return Array(es - bs + 1)
			.fill(0)
			.map((_, i) => (bs + i + '').padStart(2, '0'));
	};
}
